import Link from './router-link'
import View from './router-view'
import HashHistory from './hash-history'
import HTML5History from './html-history'

export let _Vue
export default class VueRouter {
    static install(Vue) {
        // 1.判断VueRouter是否已经被注册过
        if (VueRouter.install.installed) {
            return
        }
        VueRouter.install.installed = true
        // 2.把vue构造函数记录到全局变量
        _Vue = Vue

        // 3.把创建Vue实例时候传入的router对象注入到Vue实例上
        const isDef = v => v !== undefined
        Vue.mixin({
            beforeCreate() {
                // 组件选项中没有router
                if (isDef(this.$options.router)) {
                    this._routerRoot = this
                    this._router = this.$options.router
                    // 提供全局$router和$route
                    _Vue.prototype.$router = this.$options.router
                    _Vue.prototype.$route = {}
                }
            }
        })

        // 注册RouterView和RouterLink组件
        Vue.component('RouterView', View)
        Vue.component('RouterLink', Link)
    }

    constructor(options) {
        this.options = options
        this.routeMap = {}
        const mode = options.mode || 'history'
        this.mode = mode

        // observable
        this.data = _Vue.observable({
            current: '/'
        })
        this.createRouteMap()

        switch (mode) {
            case 'history':
                this.history = new HTML5History(this, options.base)
                break
            case 'hash':
                this.history = new HashHistory(this, options.base, this.fallback)
                break
            default:
                if (process.env.NODE_ENV !== 'production') {
                    console.log(false, `invalid mode: ${mode}`)
                }
        }
    }

    createRouteMap() {
        // 遍历所有的路由规则 吧路由规则解析成键值对的形式存储到routeMap中
        this.options.routes.forEach(route => {
            this.routeMap[route.path] = route.component
        })
    }

    push(location) {
        this.history.push(location)
    }

    replace(location) {
        this.history.replace(location)
    }

    go(n) {
        this.history.go(n)
    }

    back() {
        this.go(-1)
    }

    forward() {
        this.go(1)
    }
}